package com.jiangy.oauth2login.config;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.function.BiConsumer;

/**
 * OAuth2Login 登录成功处理器
 * <p>创建时间: 2024/8/12 </p>
 *
 * @author <a href="mailto:jiangliu0316@outlook.com" rel="nofollow">蒋勇</a>
 */
@Component
public class OAuth2LoginAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    // `SavedRequestAwareAuthenticationSuccessHandler` 是 Spring Security 中的一个认证成功处理程序。
    //它的主要作用是在用户认证成功后，处理重定向逻辑。特别是当用户在访问一个需要认证的页面时被重定向到登录页面，认证成功后，`SavedRequestAwareAuthenticationSuccessHandler` 会尝试根据之前保存的请求信息（`SavedRequest`）将用户重定向回他们最初想要访问的页面。
    //这样可以提供更友好和连贯的用户体验，确保用户在认证成功后能够回到他们最初试图访问的受保护资源，而不是简单地重定向到一个默认的页面。
    //例如，如果用户未登录时尝试访问 `/protected/page` ，被重定向到登录页面进行登录，认证成功后，`SavedRequestAwareAuthenticationSuccessHandler` 会将用户重定向回 `/protected/page` 。
    private final AuthenticationSuccessHandler delegate = new SavedRequestAwareAuthenticationSuccessHandler();
    private BiConsumer<OAuthLoginContext, OAuth2User> oauth2UserHandler = (authenticationToken, user) -> {
    };

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        System.out.println("====OAuth2 Login onAuthenticationSuccess====");
        if (authentication instanceof OAuth2AuthenticationToken token) {
            if (authentication.getPrincipal() instanceof OAuth2User oauth2User) {
                System.out.println("====OAuth2 Login oauth2User====");
                System.out.println(oauth2User.getName());
                this.oauth2UserHandler.accept(new OAuthLoginContext(token), oauth2User);
            }
        }
        this.delegate.onAuthenticationSuccess(request, response, authentication);
    }

    public void setOauth2UserHandler(BiConsumer<OAuthLoginContext, OAuth2User> oauth2UserHandler) {
        this.oauth2UserHandler = oauth2UserHandler;
    }
}
